package nz.ac.massey.xTarsier.gui;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.BorderLayout;
import javax.swing.SwingUtilities;
import java.awt.Point;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JFrame;
import javax.swing.JDialog;
import java.awt.Dimension;
import javax.swing.JEditorPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.JScrollPane;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Toolkit;

import javax.swing.JTextField;
import java.awt.Insets;
import java.io.FileNotFoundException;

import javax.swing.JButton;

import org.apache.commons.jxpath.JXPathContext;

import nz.ac.massey.xTarsier.gui.components.FileTree;
import nz.ac.massey.xTarsier.structure.*;

public class XTarsierGui {

	private JFrame jFrame = null;  

	private JPanel jContentPane = null;

	private JMenuBar jJMenuBar = null;

	private JMenu fileMenu = null;

	private JMenu helpMenu = null;

	private JMenuItem exitMenuItem = null;

	private JMenuItem aboutMenuItem = null;

	private JDialog aboutDialog = null; 

	private JPanel aboutContentPane = null;

	private JEditorPane aboutEditorPane = null;

	private JSplitPane verticalSplitPane = null;

	private FileTree pathTree = null;

	private JSplitPane horizontalSplitPane = null;

	private JScrollPane resultsScrollPane = null;

	private JPanel bottomPanel = null;

	private JLabel directoryLabel = null;

	private JLabel xPathQueryLabel = null;

	private JTextField directoryTextField = null;

	private JTextField xPathTextField = null;

	private JButton executeButton = null;

	private JButton setButton = null;

	private JScrollPane treeScrollPane = null;

	private JFileChooser fc = new JFileChooser();

	private SystemFile fileForQuery;  

	private JEditorPane resultsEditorPane = null;

	public XTarsierGui(){
		getJFrame().setVisible(true);
	}
	
	/**
	 * This method initializes jFrame
	 * 
	 * @return javax.swing.JFrame
	 */
	private JFrame getJFrame() {
		if (jFrame == null) {
			jFrame = new JFrame();
			jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			jFrame.setJMenuBar(getJJMenuBar());
			jFrame.setSize(850, 535);
			jFrame.setContentPane(getJContentPane());
			jFrame.setTitle("XTarsier");
			jFrame.setIconImage(Toolkit.getDefaultToolkit().getImage("tarsier.jpeg"));
		}
		return jFrame;
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getVerticalSplitPane(), BorderLayout.CENTER);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jJMenuBar	
	 * 	
	 * @return javax.swing.JMenuBar	
	 */
	private JMenuBar getJJMenuBar() {
		if (jJMenuBar == null) {
			jJMenuBar = new JMenuBar();
			jJMenuBar.add(getFileMenu());
			jJMenuBar.add(getHelpMenu());
		}
		return jJMenuBar;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getFileMenu() {
		if (fileMenu == null) {
			fileMenu = new JMenu();
			fileMenu.setText("File");
			fileMenu.add(getExitMenuItem());
		}
		return fileMenu;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getHelpMenu() {
		if (helpMenu == null) {
			helpMenu = new JMenu();
			helpMenu.setText("Help");
			helpMenu.add(getAboutMenuItem());
		}
		return helpMenu;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getExitMenuItem() {
		if (exitMenuItem == null) {
			exitMenuItem = new JMenuItem();
			exitMenuItem.setText("Exit");
			exitMenuItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					System.exit(0);
				}
			});
		}
		return exitMenuItem;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getAboutMenuItem() {
		if (aboutMenuItem == null) {
			aboutMenuItem = new JMenuItem();
			aboutMenuItem.setText("About");
			aboutMenuItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					JDialog aboutDialog = getAboutDialog();
					aboutDialog.pack();
					Point loc = getJFrame().getLocation();
					loc.translate(20, 20);
					aboutDialog.setLocation(loc);
					aboutDialog.setVisible(true);
				}
			});
		}
		return aboutMenuItem;
	}

	/**
	 * This method initializes aboutDialog	
	 * 	
	 * @return javax.swing.JDialog
	 */
	private JDialog getAboutDialog() {
		if (aboutDialog == null) {
			aboutDialog = new JDialog(getJFrame(), true);
			aboutDialog.setTitle("About XTarsier");
			aboutDialog.setSize(new Dimension(364, 202));
			aboutDialog.setContentPane(getAboutContentPane());
		}
		return aboutDialog;
	}

	/**
	 * This method initializes aboutContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getAboutContentPane() {
		if (aboutContentPane == null) {
			aboutContentPane = new JPanel();
			aboutContentPane.setLayout(new BorderLayout());
			aboutContentPane.add(getAboutEditorPane(), BorderLayout.CENTER);
		}
		return aboutContentPane;
	}

	/**
	 * This method initializes aboutEditorPane	
	 * 	
	 * @return javax.swing.JEditorPane	
	 */
	private JEditorPane getAboutEditorPane() {
		if (aboutEditorPane == null) {
			aboutEditorPane = new JEditorPane();
			aboutEditorPane.setContentType("text/html");
			aboutEditorPane.setText("<html><body><center><br><br><b>XTarsier Version <i>0.1 alpha</i><br><br>Credits:<br><i>Oscar Cao<br>Graham Jensen</i></center><br><br></body></html>");
		}
		return aboutEditorPane;
	}

	/**
	 * This method initializes verticalSplitPane	
	 * 	
	 * @return javax.swing.JSplitPane	
	 */
	private JSplitPane getVerticalSplitPane() {
		if (verticalSplitPane == null) {
			verticalSplitPane = new JSplitPane();
			verticalSplitPane.setDividerSize(1);
			verticalSplitPane.setLeftComponent(getTreeScrollPane());
			verticalSplitPane.setRightComponent(getHorizontalSplitPane());
		}
		return verticalSplitPane;
	}

	/**
	 * This method initializes pathTree	
	 * 	
	 * @return javax.swing.JTree	
	 */
	private JTree getPathTree() {
		if (pathTree == null) {
			try {
				pathTree = new FileTree("/");
				setupXPath("/");
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			}
		}
		return pathTree;
	}

	private JTree getPathTree(String path) {
		try {
			pathTree = new FileTree(path);
			setupXPath(path);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}


		return pathTree;
	}
	/**
	 * This method initializes horizontalSplitPane	
	 * 	
	 * @return javax.swing.JSplitPane	
	 */
	private JSplitPane getHorizontalSplitPane() {
		if (horizontalSplitPane == null) {
			horizontalSplitPane = new JSplitPane();
			horizontalSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
			horizontalSplitPane.setMinimumSize(new Dimension(550, 55));
			horizontalSplitPane.setPreferredSize(new Dimension(550, 55));
			horizontalSplitPane.setDividerLocation(420);
			horizontalSplitPane.setTopComponent(getResultsScrollPane());
			horizontalSplitPane.setBottomComponent(getBottomPanel());
			horizontalSplitPane.setDividerSize(1);
		}
		return horizontalSplitPane;
	}

	/**
	 * This method initializes resultsScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getResultsScrollPane() {
		if (resultsScrollPane == null) {
			resultsScrollPane = new JScrollPane();
			resultsScrollPane.setViewportView(getResultsEditorPane());
		}
		return resultsScrollPane;
	}
	
	/**
	 * This method initializes bottomPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getBottomPanel() {
		if (bottomPanel == null) {
			GridBagConstraints gridBagConstraints = new GridBagConstraints();
			gridBagConstraints.gridy = 0;
			gridBagConstraints.gridx = 2;
			GridBagConstraints gridBagConstraints7 = new GridBagConstraints();
			gridBagConstraints7.gridx = 2;
			gridBagConstraints7.gridy = 1;
			GridBagConstraints gridBagConstraints6 = new GridBagConstraints();
			gridBagConstraints6.fill = GridBagConstraints.VERTICAL;
			gridBagConstraints6.gridx = 1;
			gridBagConstraints6.gridy = 1;
			gridBagConstraints6.weightx = 1.0;
			gridBagConstraints6.insets = new Insets(0, 61, 4, 123);
			GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
			gridBagConstraints5.fill = GridBagConstraints.VERTICAL;
			gridBagConstraints5.gridx = 1;
			gridBagConstraints5.gridy = 0;
			gridBagConstraints5.weightx = 1.0;
			gridBagConstraints5.insets = new Insets(4, 61, 0, 123);
			GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
			gridBagConstraints4.insets = new Insets(2, 5, 6, 66);
			gridBagConstraints4.gridy = 1;
			gridBagConstraints4.gridx = 0;
			GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
			gridBagConstraints3.insets = new Insets(6, 0, 2, 61);
			gridBagConstraints3.gridy = 0;
			gridBagConstraints3.gridx = 0;
			xPathQueryLabel = new JLabel();
			xPathQueryLabel.setText("XPath Query:   ");
			directoryLabel = new JLabel();
			directoryLabel.setText("Root Directory:");
			bottomPanel = new JPanel();
			bottomPanel.setLayout(new GridBagLayout());
			bottomPanel.setMinimumSize(new Dimension(0, 50));
			bottomPanel.setMaximumSize(new Dimension(2147483647, 50));
			bottomPanel.setPreferredSize(new Dimension(759, 50));
			bottomPanel.add(directoryLabel, gridBagConstraints3);
			bottomPanel.add(xPathQueryLabel, gridBagConstraints4);
			bottomPanel.add(getDirectoryTextField(), gridBagConstraints5);
			bottomPanel.add(getXPathTextField(), gridBagConstraints6);
			bottomPanel.add(getSetButton(), gridBagConstraints);
			bottomPanel.add(getExecuteButton(), gridBagConstraints7);
		}
		return bottomPanel;
	}

	/**
	 * This method initializes directoryTextField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getDirectoryTextField() {
		if (directoryTextField == null) {
			directoryTextField = new JTextField();
			directoryTextField.setPreferredSize(new Dimension(500, 20));
			directoryTextField.setMaximumSize(new Dimension(500, 20));
			directoryTextField.setEditable(false);
			directoryTextField.setMinimumSize(new Dimension(500, 20));
		}
		return directoryTextField;
	}

	/**
	 * This method initializes xPathTextField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getXPathTextField() {
		if (xPathTextField == null) {
			xPathTextField = new JTextField();
			xPathTextField.setMinimumSize(new Dimension(450, 20));
			xPathTextField.setMaximumSize(new Dimension(450, 20));
			xPathTextField.setPreferredSize(new Dimension(450, 20));
		}
		return xPathTextField;
	}

	/**
	 * This method initializes executeButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getExecuteButton() {
		if (executeButton == null) {
			executeButton = new JButton();
			executeButton.setPreferredSize(new Dimension(80, 20));
			executeButton.setMaximumSize(new Dimension(80, 20));
			executeButton.setText("Execute");
			executeButton.setMinimumSize(new Dimension(80, 20));
			executeButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					try {
						java.util.Iterator i = queryXpath(fileForQuery, xPathTextField.getText());
						String htmlOutput = "<html>" +
												"<head>" +
												"</head>" +
												"<body>" +
													"<table border=\"2\" width=\"100%\" align=\"left\" cellspacing=\"0\" cellpadding=\"0\">" +
														"<TR>" +
															"<TD>" +
															"</TD>" +
															"<TD>" +
																"Filename" +
															"</TD>" +
															"<TD>" +
																"Filesize" +
															"</TD>" +
															"<TD>" +
																"Absolute filepath" +
															"</TD>" +
														"</TR>";
						while ( i.hasNext())
						{
							SystemFile sf = ((SystemFile)i.next());
							//if (sf.isFile()) { nz.ac.massey.xTarsier.structure.File file = (File)sf;}
							
							String AbPath = sf.getAbsolutePath();
							String name = sf.getName();
							htmlOutput = htmlOutput + 	"<TR>" +
															"<TD>";
																if (sf.isFile()) {
																	//Icon title = new ImageIcon(ClassLoader.getSystemResource("images/file.jpeg"));
																	htmlOutput = htmlOutput + "<img src=\"/file.jpeg\" alt=\"file image\">";
																}
																else{
																	//Icon title = new ImageIcon(ClassLoader.getSystemResource("images/folder.jpeg"));
																	htmlOutput = htmlOutput + "<img src=\"/folder.jpeg\" alt=\"folder image\">";
																}
								  htmlOutput = htmlOutput + "</TD>" +
															"<TD>" +
																name.trim() +
															"</TD>" +
															"<TD>";
																if (sf.isFile()) {
																	htmlOutput = htmlOutput + ((File)sf).getFileSize() + " bytes";
																}
								  htmlOutput = htmlOutput + "</TD>" +
															"<TD>" +
																AbPath.trim() +
															"</TD>" +
														"</TR>";
														
						}
						htmlOutput = htmlOutput + 
													"</table>" +
												"</body>" +
											"</html>";
						resultsEditorPane.setText(htmlOutput);
						System.out.println(htmlOutput);
					}
					catch (RuntimeException e1) {
						String errorMessage = "The following error has occurred:<br><br> <b>" + 
											e1.toString() +
											"</b><br><br>This is most likely to be caused by an invalid XPath query. <br> Please Check XPath query.";
						resultsEditorPane.setText(errorMessage);
					}
				}
			});
		}
		return executeButton;
	}

	/**
	 * This method initializes setButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getSetButton() {
		if (setButton == null) {
			setButton = new JButton();
			setButton.setMaximumSize(new Dimension(80, 20));
			setButton.setPreferredSize(new Dimension(80, 20));
			setButton.setText("Set");
			setButton.setMinimumSize(new Dimension(80, 20));
			setButton.addActionListener(new java.awt.event.ActionListener() {   
				public void actionPerformed(java.awt.event.ActionEvent e) {    
					fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
					int returnVal = fc.showDialog(jFrame, "Select Directory");
					if (returnVal == JFileChooser.APPROVE_OPTION){
						String newPath = fc.getSelectedFile().getPath().toString();
						directoryTextField.setText(newPath);
						setupXPath(newPath);
						verticalSplitPane.remove(treeScrollPane);
						verticalSplitPane.add(getTreeScrollPane(newPath));
					}
				}

			});
		}
		return setButton;
	}

	/**
	 * This method initializes treeScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getTreeScrollPane() {
		if (treeScrollPane == null) {
			treeScrollPane = new JScrollPane(getPathTree());
			treeScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
			treeScrollPane.setMinimumSize(new Dimension(200, 22));
		}
		return treeScrollPane;
	}

	/**
	 * This method initializes treeScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getTreeScrollPane(String path) {
		treeScrollPane = new JScrollPane(getPathTree(path));
		treeScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		treeScrollPane.setMinimumSize(new Dimension(200, 22));
		return treeScrollPane;
	}

	/**
	 * This method initializes resultsEditorPane	
	 * 	
	 * @return javax.swing.JEditorPane	
	 */
	private JEditorPane getResultsEditorPane() {
		if (resultsEditorPane == null) {
			resultsEditorPane = new JEditorPane();
			resultsEditorPane.setContentType("text/html");
		}
		return resultsEditorPane;
	}

	private void setupXPath(String path){
		fileForQuery = FileConverter.convertFile(new java.io.File(path));

	}

	private java.util.Iterator<SystemFile> queryXpath(SystemFile f, String query) {
		JXPathContext j = JXPathContext.newContext(f);
		java.util.Iterator i = j.iterate(query);
		return i;
	}
}
